package com.cl.springbootfiles.controller;

import com.cl.springbootfiles.vo.FileVO;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Controller
public class FileController {
    private static final Logger log = LoggerFactory.getLogger(FileController.class);
    public static final String REDIRECT = "redirect:/file/list";
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd HH_mm_ss");
    @Value("${save-path}")
    private String savePath;

    public FileController() {
    }

    @GetMapping({"/", "/file"})
    public String index() {
        return REDIRECT;
    }

    @PostMapping({"/file/upload"})
    public String upload(@RequestParam("file") MultipartFile[] multipartFiles) {
        for (MultipartFile multipartFile : multipartFiles) {
            try {
                if (null == multipartFile || multipartFile.isEmpty()) {
                    throw new RuntimeException("上传文件不能为空");
                }

                File directory = new File(savePath);
                if (!directory.exists()) {
                    directory.mkdirs();
                }

                String filename = multipartFile.getOriginalFilename();
                filename = ObjectUtils.isEmpty(filename) ? "default_file" : filename;
                File file = new File(savePath, filename);
                if (file.exists()) {
                    FileUtils.moveFile(file, new File(savePath + filename + "." + this.dateFormat.format(new Date(file.lastModified()))));
                }
                multipartFile.transferTo(file.toPath());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return REDIRECT;
    }

    @GetMapping({"/file/download/{filename}"})
    public void downLoad(HttpServletResponse response, @PathVariable("filename") String filename) {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        ServletOutputStream os = null;

        try {
            File file = new File(savePath + filename);
            if (!file.exists()) {
                throw new RuntimeException(String.format("文件: %s不存在", filename));
            }

            filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
            response.setHeader("Content-Type", "multipart/form-data");
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "attachment;fileName=" + filename);
            byte[] buffer = new byte[1024];
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            os = response.getOutputStream();

            while (bis.read(buffer) != -1) {
                os.write(buffer);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(os, bis, fis);
        }

    }

    @GetMapping({"/file/list"})
    public String list(Model model) {
        File directory = new File(savePath);
        File[] files = directory.listFiles();
        List<FileVO> fileVOs;
        if (null == files) {
            fileVOs = Collections.emptyList();
        } else {
            fileVOs = Arrays.stream(files)
                    .filter(File::isFile)
                    .map(file -> FileVO.builder().fileName(file.getName()).fileSize(FileVO.formatFileSize(file.length())).lastModified(new Date(file.lastModified())).build())
                    .sorted((o1, o2) -> o2.getLastModified().compareTo(o1.getLastModified()))
                    .collect(Collectors.toList());
        }
        model.addAttribute("fileVOs", fileVOs);
        return "file";
    }

    @GetMapping({"/file/delete/{filename}"})
    public String delete(@PathVariable("filename") String filename) {
        File file = new File(savePath, filename);
        FileUtils.deleteQuietly(file);
        return REDIRECT;
    }

    @GetMapping({"/file/delete_all"})
    public String delete() {
        File[] files = new File(savePath).listFiles();
        if (null != files) {
            Arrays.stream(files).filter(File::isFile).forEach(FileUtils::deleteQuietly);
        }
        return REDIRECT;
    }

}
